package com.juvenxu.mvnbook.account.persist;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentFactory;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

import javax.security.auth.login.AccountException;
import java.io.*;
import java.util.List;

/**
 * @author huyong
 * @version 1.0.0
 * @description
 * @date 2015/4/24 13:45
 */
public class AccountPersistServiceImpl implements AccountPersistService{

	public static final String ELEMENT_ROOT = "account-persist";
	public static final String ELEMENT_ACCOUNTS = "accounts";
	public static final String ELEMENT_ACCOUNT_ID = "id";
	public static final String ELEMENT_ACCOUNT_NAME = "name";
	public static final String ELEMENT_ACCOUNT_EMAIL = "email";
	public static final String ELEMENT_ACCOUNT_PASSWORD = "password";
	public static final String ELEMENT_ACCOUNT_ACTIVATED = "activated";
	public static final String ELEMENT_ACCOUNT = "account";
	private String file;

	private SAXReader reader = new SAXReader();

	private Document readDocument() throws AccountException{
		File dataFile = new File(file);

		if(!dataFile.exists()){
			dataFile.getParentFile().mkdirs();
			Document doc = DocumentFactory.getInstance().createDocument();
			Element rootEle = doc.addElement(ELEMENT_ROOT);
			rootEle.addElement(ELEMENT_ACCOUNTS);
			writeDocument(doc);
		}
		try{
			return reader.read(new File(file));
		}catch (DocumentException e){
			throw new AccountException("Unable to read data xml");
		}
	}

	private void writeDocument(Document doc) throws AccountException{
		Writer out = null;

		try{
			out = new OutputStreamWriter(new FileOutputStream(file), "utf-8");
			XMLWriter writer = new XMLWriter(out, OutputFormat.createPrettyPrint());
			writer.write(doc);
		}catch (IOException e){
			throw new AccountException("Unable to write data xml");
		}finally {
			try{
				if(out!=null) out.close();
			}catch (IOException e){
				throw new AccountException("Unbale to close data xml writer");
			}
		}
	}

	@Override
	public Account createAccount(Account account) throws AccountException {
		Document doc = readDocument();

		Element accountsEle = doc.getRootElement().element(ELEMENT_ACCOUNTS);
		Element accountEle = accountsEle.addElement(ELEMENT_ACCOUNT);

		accountEle.addElement(ELEMENT_ACCOUNT_ID).addText(account.getId());
		accountEle.addElement(ELEMENT_ACCOUNT_NAME).addText(account.getName());
		accountEle.addElement(ELEMENT_ACCOUNT_EMAIL).addText(account.getEmail());
		accountEle.addElement(ELEMENT_ACCOUNT_PASSWORD).addText(account.getPassword());
		accountEle.addElement(ELEMENT_ACCOUNT_ACTIVATED).addText(String.valueOf(account.isActivated()));

		writeDocument(doc);
		return account;
	}

	@Override
	public Account readAccount(String id) throws AccountException {
		Document doc = readDocument();

		Element accountsEle = doc.getRootElement().element(ELEMENT_ACCOUNTS);

		for(Element accountEle : (List<Element>)accountsEle.elements()){
			if(accountEle.elementText(ELEMENT_ACCOUNT_ID).equals(id)){
				return buildAccount(accountEle);
			}
		}
		return null;
	}

	private Account buildAccount(Element element){
		Account account = new Account();

		account.setId(element.elementText(ELEMENT_ACCOUNT_ID));
		account.setName(element.elementText(ELEMENT_ACCOUNT_NAME));
		account.setEmail(element.elementText(ELEMENT_ACCOUNT_EMAIL));
		account.setPassword(element.elementText(ELEMENT_ACCOUNT_PASSWORD));
		account.setActivated("true".equals(element.elementText(ELEMENT_ACCOUNT_ACTIVATED)));

		return account;
	}

	@Override
	public Account updateAccount(Account account) throws AccountException {
		return null;
	}

	@Override
	public void deleteAccount(String id) throws AccountException {

	}

	public String getFile() {
		return file;
	}

	public void setFile(String file) {
		this.file = file;
	}
}
